package com.lvmama.pangolin.proces;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import com.lvmama.pangolin.HBaseOper.HotelHBEntityOperation;
import com.lvmama.pangolin.common.Constant;
import com.lvmama.pangolin.common.DateUtil;
import com.lvmama.pangolin.common.RowkeyGenerator;
import com.lvmama.pangolin.common.StringTools;
import com.lvmama.pangolin.entity.ConvertTask;
import com.lvmama.pangolin.entity.RelevanceProduct;
import com.lvmama.pangolin.entity.RuleLevelModel;
import com.lvmama.pangolin.entity.Task_History;
import com.lvmama.pangolin.entity.hotel.HotelCdetail;
import com.lvmama.pangolin.entity.hotel.HotelCommodityDetail;
import com.lvmama.pangolin.entity.hotel.HotelPdetail;
import com.lvmama.pangolin.entity.hotel.HotelProductDetail;
import com.lvmama.pangolin.hbaseutil.HBaseUtils;
import com.lvmama.pangolin.hotel.service.HotelCdetailService;
import com.lvmama.pangolin.hotel.service.HotelCommodityDetailErrorService;
import com.lvmama.pangolin.hotel.service.HotelCommodityDetailService;
import com.lvmama.pangolin.hotel.service.HotelNewProductService;
import com.lvmama.pangolin.hotel.service.HotelPdetailService;
import com.lvmama.pangolin.hotel.service.HotelProductDetailService;
import com.lvmama.pangolin.service.RelevanceProductService;
import com.lvmama.pangolin.util.RuleUtil;

@Component
public class HotelDataProcess {
	/**
	 * @Title：TC_Data_Process.java
	 * @Author:zhoutianqi
	 * @Description:
	 * @Date：2017年2月15日下午3:12:25
	 */
	private Logger logger = Logger.getLogger(HotelDataProcess.class);
	@Autowired
	private RuleUtil ruleUtil;
	@Autowired
	private HBaseUtils hBaseUtil;
	@Autowired
	private RelevanceProductService reProService;
	@Autowired
	private HotelHBEntityOperation hotelHBEntityOperation;
	@Autowired
	private HotelProductDetailService hotelProductDetailService;
	@Autowired
	private HotelCommodityDetailService hotelCommodityDetailService;
	@Autowired
	private HotelCommodityDetailErrorService hotelCommodityDetailErrorService;
	@Autowired
	private HotelPdetailService hotelPdetailService;
	@Autowired
	private HotelNewProductService hotelNewProductService;
	@Autowired
	private HotelCdetailService hotelCdetailService;
	@Async
	public String executeProcess(List<ConvertTask> taskList) {
		int reallyDoneProductNum = 0;//实际处理产品数据量
		for(ConvertTask task:taskList){
			if (!ruleUtil.hasTaskIDAndCity(task)) {
				logger.error("Task任务：" + task.getId() + "没有必要的taskID,CityCode");
				ruleUtil.updateTimerStatus(task, Constant.DATA_ERROR_STATE_CODE);
				continue;
			}
			try {
				Map<String, String> map = new HashMap<String, String>();
				map.put("taskId", task.getTaskId());
				map.put("cityCode", task.getGranularityValue());
				map.put("productId", task.getProductId());
				map.put("companyCode", task.getCompanyCode());
				//理论上、实际上只有一个产品
				List<HotelPdetail> hotelPdetailList = hotelPdetailService.findListByMap(map);
				//产品不存在就没得玩了
				if(hotelPdetailList.size()<=0){
					ruleUtil.updateTimerStatus(task, Constant.DATA_SUCCESS_STATE_CODE);
					continue;
				}
				HotelPdetail hotelPdetail = hotelPdetailList.get(0);
				//抓取库里面商品detailId==产品detailId
				map.clear();
				map.put("detailId", hotelPdetail.getDetailId());
				List<HotelCdetail> cdetailList = hotelCdetailService.findListByMap(map);
				//商品不存在也没得玩了
				if(cdetailList.size()<=0){
					ruleUtil.updateTimerStatus(task, Constant.DATA_SUCCESS_STATE_CODE);
					continue;
				}
				//记录成功入库的商品
				List<HotelCdetail> checkedDoneList = new ArrayList<>();
				//先处理商品
				//是否有新商品
				boolean hasNewCommodity = false;
				for(HotelCdetail hotelCdetailTtem:cdetailList){
					//商品价格有问题，忽略该商品
					if(!StringTools.isValid(hotelCdetailTtem.getSalePrice()) || 
							!StringTools.isDoubleNumeric(hotelCdetailTtem.getSalePrice())){
						//这里可以考虑加日志表，记录错误信息
						continue;
					}
					//暂时把对商品ID是否纯数字的校验注掉，原因是携程酒店商品ID后面跟随字母
					/*if(!StringTools.isNumeric(hotelCdetailTtem.getCommodityId())){
						//商品ID包含特殊字符,过滤掉
						continue;
					}*/
					//商品房型不能为空
					if(!StringTools.isValid(hotelCdetailTtem.getRoomType())){
						continue;
					}
					//商品公司名称字段不能为空
					if(!StringTools.isValid(hotelCdetailTtem.getCompanyCode())){
						if(StringTools.isValid(hotelPdetail.getCompanyCode())){
							hotelCdetailTtem.setCompanyCode(hotelPdetail.getCompanyCode());
						}else{continue;}
					}
					//商品ID不能是空
					if(!StringTools.isValid(hotelCdetailTtem.getCommodityId())){
						continue;
					}
					boolean commodityCheckedDone = commodityPriceVerify(task,hotelPdetail,hotelCdetailTtem);
					if(commodityCheckedDone) {
						Map<String,String> paramMap = new HashMap<String, String>();
						paramMap.put("productId", hotelCdetailTtem.getProductId());
						paramMap.put("commodityId", hotelCdetailTtem.getCommodityId());
						//公司名称
						paramMap.put("companyCode", hotelCdetailTtem.getCompanyCode());
						//从转化表中读取数据，看是否已存在
						List<HotelCommodityDetail> convertedCommList = hotelCommodityDetailService.findListByMap(paramMap);
						HotelCommodityDetail existedCommodityDetail = null;
						if(convertedCommList.size()>0){
							existedCommodityDetail = convertedCommList.get(0);
						}
						/*//避免出现不同房型，相同商品ID 导致入表insert时主键冲突
						if(existedCommodityDetail!=null && !existedCommodityDetail.getRoomType().trim().equals(hotelCdetailTtem.getRoomType().trim())){
							continue;
						}*/
						//task数据入表
						synchronized (RuleUtil.class) {
							//存储产品的入店时间，因为价格校验的时候会用到来生成可能的rowkey进行查询
							ruleUtil.addTaskInfo(hotelCdetailTtem.getTaskId(), hotelPdetail.getComeDate(), hotelPdetail.getCompanyCode(),
									Constant.HOTEL_BUS_TYPE, Constant.COMMODITY_LEVEL_TYPE);
							ruleUtil.addTaskInfo(hotelPdetail.getTaskId(), hotelPdetail.getComeDate(), hotelPdetail.getCompanyCode(),
									Constant.HOTEL_BUS_TYPE, Constant.PRODUCT_LEVEL_TYPE);
						}
						// 当前商品rowkey
						String rowkey = RowkeyGenerator.generateCommodityRowkeyWithCompany(
								hotelCdetailTtem.getCommodityId(), hotelPdetail.getCompanyCode(),
								hotelPdetail.getComeDate(), hotelCdetailTtem.getProductId());
						//商品名称不能为空，后需要做商品关键字匹配关联
						if(!StringTools.isValid(hotelCdetailTtem.getCommodityName())){
							hotelCdetailTtem.setCommodityName(hotelCdetailTtem.getRoomType());
						}
						checkedDoneList.add(hotelCdetailTtem);
						if(existedCommodityDetail!=null){
							hotelCdetailTtem.setDetailId(existedCommodityDetail.getId());
							hotelCommodityDetailService.updateByCdetail(hotelCdetailTtem);
						}else{
							hotelCdetailTtem.setDetailId(rowkey);
							hotelCommodityDetailService.saveCdetail(hotelCdetailTtem);
						}
						// 价格团期数据不存在，存储当前商品价格数据
						hotelHBEntityOperation.saveHistoryPrice(hotelPdetail, hotelCdetailTtem, rowkey,
								Constant.HB_VARIABLE_FAMILY, Constant.HOTEL_COMMODITY_PRICE_H);
						hotelCdetailTtem.setDetailId(rowkey);
						hotelHBEntityOperation.saveHotelCommodity(hotelCdetailTtem, Constant.HOTEL_COMMODITY_H, Constant.HB_VARIABLE_FAMILY);
					}
				}
				//如果没有商品入库，忽略产品
				if(checkedDoneList.isEmpty()){
					ruleUtil.updateTimerStatus(task, Constant.DATA_SUCCESS_STATE_CODE);
					continue;
				}
				reallyDoneProductNum++;
				commodityAttrNum(checkedDoneList,hotelPdetail);
				saveHotelProduct(task,hotelPdetail,hasNewCommodity);
				ruleUtil.updateTimerStatus(task, Constant.DATA_SUCCESS_STATE_CODE);
				logger.info(">>>>>>当前线程："+Thread.currentThread().getId()+";"+hotelPdetail.getCompanyCode()+"任务：[" + task.getId() + "];执行完毕！<<<<<<");
			} catch (Exception e) {
				logger.error("HotelProcess任务处理异常-------任务编码：" + task.getId() + "---异常信息：" + e.getMessage());
				ruleUtil.updateTimerStatus(task, Constant.DATA_ERROR_STATE_CODE);
			}
		}
		logger.info(">>>>>>总共："+taskList.size()+"酒店个产品，实际处理酒店个数："+reallyDoneProductNum+"执行完毕！<<<<<<");
		return null;
	}
	/**
	 * 商品房型数量
	 * 商品数量
	 * 优惠数量
	*/
	private void commodityAttrNum(List<HotelCdetail> checkedDoneList,HotelPdetail hotelPdetail) {
		int roomTypeNum = 0;
		int preferentialNum = 0;
		Map<String,String> sb = new HashMap<>();
		for(HotelCdetail item:checkedDoneList){
			if(!sb.containsKey(item.getRoomType())){
				sb.put(item.getRoomType(), item.getRoomType());
				roomTypeNum++;
			}
			if(StringTools.isValid(item.getPreferential())){
				preferentialNum++;
			}
		}
		hotelPdetail.setRoomTypeNum(roomTypeNum);
		hotelPdetail.setPreferentialNum(preferentialNum);
		hotelPdetail.setCommodityNum(checkedDoneList.size());
	}
	@Transactional
	private void saveHotelProduct(ConvertTask task, HotelPdetail hotelPdetail,boolean hasNewCommodity) {
		Map<String,String> paramMap = new HashMap<>();
		paramMap.put("productId", hotelPdetail.getProductId());
		paramMap.put("companyCode", hotelPdetail.getCompanyCode());
		List<HotelProductDetail> existProductList = hotelProductDetailService.findListByMap(paramMap);
		HotelProductDetail existProduct = null;
		String productRowkey = RowkeyGenerator.generateProductRowkeyWithCompany(hotelPdetail.getProductId(), hotelPdetail.getCompanyCode(),
				hotelPdetail.getComeDate(), hotelPdetail.getTaskId());
		if(existProductList.size()>0){
			//只存在一条数据
			existProduct = existProductList.get(0);
			hotelPdetail.setDetailId(existProduct.getId());
			hotelProductDetailService.updateHotelPdetail(hotelPdetail);
			//处理产品关联关系
			dealHotelProductDfaultLink(hotelPdetail,existProduct,null,hasNewCommodity);
		}else{
			hotelPdetail.setDetailId(productRowkey);
			//新抓酒店为新产品，入新产品表
			hotelNewProductService.savePdetail(hotelPdetail);
			//新抓酒店为新产品，入产品表
			hotelProductDetailService.saveHotelPdetail(hotelPdetail);
			//处理产品关联关系
			dealHotelProductDfaultLink(hotelPdetail,null,productRowkey,hasNewCommodity);
		}
		hotelPdetail.setDetailId(productRowkey);
		hotelHBEntityOperation.saveHotelProduct(hotelPdetail, Constant.HOTEL_PRODUCT_H, Constant.HB_VARIABLE_FAMILY);
		
	}
	@Transactional
	private void dealHotelProductDfaultLink(HotelPdetail hotelPdetail, HotelProductDetail existProduct, String productRowkey
			,boolean hasNewCommodity) {
		if(!StringTools.isValid(hotelPdetail.getLvProductId())){
			//没有驴妈妈产品字段，无法做关联
			return;
		}
		//查询驴妈妈 酒店产品关联关系
		boolean relevance = true;
		//是否真的执行了默认关联
		boolean isLinked = false;
		RelevanceProduct queryItem = reProService.viewRelevance(hotelPdetail.getLvProductId(),Constant.HOTEL_BUS_TYPE);
		if(queryItem==null){
			relevance=false;
			queryItem=new RelevanceProduct();
			queryItem.setProdId(hotelPdetail.getLvProductId());
			queryItem.setBusinessCode(Constant.HOTEL_BUS_TYPE);
		}
		if(existProduct!=null && existProduct.getIsLink()==1){
			if(hasNewCommodity && queryItem!=null){//如果新增商品且产品关联关系未改变
				//因为抓到新商品，所以状态更新，可以人工再做商品关联
				if(queryItem.getProdIdQNR().equals(hotelPdetail.getProductId()) || 
						queryItem.getProdIdTC().equals(hotelPdetail.getProductId()) ||
						queryItem.getProdIdTN().equals(hotelPdetail.getProductId()) ||
						queryItem.getProdIdXC().equals(hotelPdetail.getProductId()) ||
						queryItem.getProdIdEL().equals(hotelPdetail.getProductId()) ||
						queryItem.getProdIdMT().equals(hotelPdetail.getProductId())){
					queryItem.setIsDeal(0);
					reProService.updateRelevance(queryItem);
				}
			}
			//如果该产品已经被非默认的产品关联，不作处理
			return;
		}
		if(hotelPdetail.getCompanyCode().equals(Constant.TN_C_CODE) && !StringTools.isValid(queryItem.getProdIdTN())){
			//对应字段为空才设置，假设关联别的就不处理
			//设置对应的产品ID和酒店名称
			queryItem.setProdIdTN(hotelPdetail.getProductId());
			queryItem.setProdNameTN(hotelPdetail.getHotelName());
			if(!relevance){
				reProService.insertTN(queryItem);
			}else{
				reProService.updateTN(queryItem);
			}
			isLinked = true;
		}else if(hotelPdetail.getCompanyCode().equals(Constant.TC_C_CODE) && !StringTools.isValid(queryItem.getProdIdTC())){
			queryItem.setProdIdTC(hotelPdetail.getProductId());
			queryItem.setProdNameTC(hotelPdetail.getHotelName());
			if(!relevance){
				reProService.insertTC(queryItem);
			}else{
				reProService.updateTC(queryItem);
			}
			isLinked = true;
		}else if(hotelPdetail.getCompanyCode().equals(Constant.XC_C_CODE) && !StringTools.isValid(queryItem.getProdIdXC())){
			queryItem.setProdIdXC(hotelPdetail.getProductId());
			queryItem.setProdNameXC(hotelPdetail.getHotelName());
			if(!relevance){
				reProService.insertXC(queryItem);
			}else{
				reProService.updateXC(queryItem);
			}
			isLinked = true;
		}else if(hotelPdetail.getCompanyCode().equals(Constant.QNR_C_CODE) && !StringTools.isValid(queryItem.getProdIdQNR())){
			queryItem.setProdIdQNR(hotelPdetail.getProductId());
			queryItem.setProdNameQNR(hotelPdetail.getHotelName());
			if(!relevance){
				reProService.insertQNR(queryItem);
			}else{
				reProService.updateQNR(queryItem);
			}
			isLinked = true;
		}else if(hotelPdetail.getCompanyCode().equals(Constant.EL_C_CODE) && !StringTools.isValid(queryItem.getProdIdEL())){
			queryItem.setProdIdEL(hotelPdetail.getProductId());
			queryItem.setProdNameEL(hotelPdetail.getHotelName());
			if(!relevance){
				reProService.insertEL(queryItem);
			}else{
				reProService.updateEL(queryItem);
			}
			isLinked = true;
		}
		
		if(isLinked){
			HotelProductDetail paramProduct = new HotelProductDetail();
			paramProduct.setIsLink(1);
			if(existProduct!=null){
				paramProduct.setId(existProduct.getId());
			}else{
				paramProduct.setId(productRowkey);
			}
			hotelProductDetailService.update(paramProduct);
		}
	}
	/**
	 * 酒店商品价格校验
	*/
	private boolean commodityPriceVerify(ConvertTask task, HotelPdetail hotelPdetail, HotelCdetail hotelCdetailTtem) {
		List<RuleLevelModel> rulelist = null;
		//1,先判断是否是特殊活动情况
		boolean needSuperRule = RuleUtil.needSuperRule(hotelCdetailTtem.getCreateTime(),ruleUtil.getHotelSuperLevelList());
		//获取到新抓取价格
		double price = Double.parseDouble(hotelCdetailTtem.getSalePrice());
		if (needSuperRule) {// 走特殊防伪
			rulelist = ruleUtil.getHotelSuperLevelList();
		} else {
			rulelist = ruleUtil.getHotelNormalLevelList();
		}
		for (RuleLevelModel level : rulelist) {
			List<Task_History> taskList = null;
			//存储可能的rowkey
			List<String> rowkeyList = null;
			int number = 0;
			double totalPrice = 0;
			double average = 0;
			double leftPrice = 0;
			double rightPrice = 0;
			if (needSuperRule) {
				if (DateUtil.isRegionDate(hotelCdetailTtem.getCreateTime(), level.getStart_date(), level.getEnd_date())) {
					taskList = ruleUtil.getPartOfTask(level.getRule_level(), hotelPdetail.getComeDate(), hotelPdetail.getCompanyCode(),
							Constant.HOTEL_BUS_TYPE, Constant.COMMODITY_LEVEL_TYPE);
					if (taskList != null && taskList.size()>0) {
						rowkeyList = new ArrayList<String>();
						for (Task_History taskItem : taskList) {
							rowkeyList.add(RowkeyGenerator.generateCommodityRowkeyWithCompany(
									hotelCdetailTtem.getCommodityId(), hotelPdetail.getCompanyCode(), taskItem.getCreate_Date(),
									hotelCdetailTtem.getProductId()));
						}

					}
				}
			} else {
				taskList = ruleUtil.getPartOfTask(level.getRule_level(), hotelPdetail.getComeDate(), hotelPdetail.getCompanyCode(),
						Constant.HOTEL_BUS_TYPE, Constant.COMMODITY_LEVEL_TYPE);
				if (taskList != null && !taskList.isEmpty()) {
					rowkeyList = new ArrayList<String>();
					for (Task_History taskItem : taskList) {
						rowkeyList.add(RowkeyGenerator.generateCommodityRowkeyWithCompany(
								hotelCdetailTtem.getCommodityId(), hotelPdetail.getCompanyCode(), taskItem.getCreate_Date(),
								hotelCdetailTtem.getProductId()));
					}
				}
			}
			if (rowkeyList != null) {
				List<Map<String, String>> dataList = hBaseUtil.get(Constant.HOTEL_COMMODITY_H,
						Constant.HB_VARIABLE_FAMILY, rowkeyList);
				if (dataList.size() > 0) {
					for (Map<String, String> map : dataList) {
						/*根据商品ID拿出所有批次的历史数据
						 * 考虑到存在不同产品ID会有相同商品ID的情况
						 * 在做校验时精确到产品ID和商品类别
						*/
						String hbProductId = map.get("productId");
						String hbCommodityId = map.get("commodityId");
						String hbCompanyCode = map.get("companyCode");
						String hbRoomType = map.get("roomType");
						if (!map.isEmpty() && hbProductId!=null && hbProductId.equals(hotelCdetailTtem.getProductId())
								&& hbCommodityId!=null && hbCommodityId.equals(hotelCdetailTtem.getCommodityId())
								&& hbCompanyCode!=null && hbCompanyCode.equals(hotelPdetail.getCompanyCode())
								&& hbRoomType!=null && hbRoomType.equals(hotelCdetailTtem.getRoomType())) {
							String hbPrice = map.get("salePrice");
							if (StringTools.isValid(hbPrice)) {
								totalPrice += Double.parseDouble(hbPrice);
								// 避免task-date对应rowkey不存在数据的情况
								number++;
							}
						}
					}
					//因为hbase是通过商品ID拿数据的，存在不同产品的两个商品ID一致的情况
					if(number>0){
						average = totalPrice / number;
						leftPrice = ruleUtil.getLeftPrice(number, average, level.getLeft_value());
						rightPrice = ruleUtil.getRightPrice(number, average, level.getRight_value());
						// 当价格超出容忍范围 记录日志
						if (price < leftPrice || price > rightPrice) {
							try {
								hotelCdetailTtem.setConvertErrorMsg("价格超出容忍值范围[price="+price+"leftPrice="+leftPrice+";rightPrice="+rightPrice+"convertTaskId:"+task.getId()+"]");
								hotelCommodityDetailErrorService.saveCdetail(hotelCdetailTtem);
							} catch (Exception e) {
								logger.error("酒店商品校验失败后入Error异常>>>");
							}
							return false;
						}
					}
				}
			}
		}
		
		return true;
	}

}
